package com.fit.utils.se;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

/**
 * Velocity 模板引擎工具
 * @author hcl
 *
 */
public class VelocityUtil {
	
	/**
	 * 模板默认编码
	 */
	public final static String TEMPLATE_ENCODING = "UTF-8";
	
	/**
	 * 根据模板地址生成模板对象
	 * @param templatePath 模板地址,相对于classpath的绝对路径(前面要加/)
	 * @param encoding 模板编码(默认为utf-8)
	 * @return
	 */
	public static Template generateTemplate(String templatePath,String encoding){
		VelocityEngine ve = new VelocityEngine();
		ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
		ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); 
		ve.init();
		encoding = EmptyUtils.isEmpty(encoding) ? TEMPLATE_ENCODING : encoding;
		return ve.getTemplate(templatePath, encoding);
	}
	
	/**
	 * 根据模板地址生成模板对象
	 * @param templatePath 模板地址,相对于classpath的绝对路径(前面要加/)
	 * @return
	 */
	public static Template generateTemplate(String templatePath){
		return generateTemplate(templatePath, null);
	}
	
	/**
	 * 根据模板文件生成模板对象
	 * @param vmFile 模板文件
	 * @param encoding 模板编码
	 * @return
	 */
	public static Template generateTemplate(File vmFile,String encoding){
		return generateTemplate(vmFile.getAbsolutePath(),encoding);
	}
	
	/**
	 * 根据模板文件生成模板对象
	 * @param vmFile 模板文件
	 * @return
	 */
	public static Template generateTemplate(File vmFile){
		return generateTemplate(vmFile.getAbsolutePath());
	}
	
	
	/**
	 * 根据模板对象生成模板实例
	 * @param context 参数域
	 * @param template 模板对象
	 * @param writerOut 输出流
	 */
	public static void generateTemplateInstance(VelocityContext context,Template template, Writer writerOut){
		try{
			if(EmptyUtils.isNotEmptys(context, template, writerOut)){
				template.merge(context, writerOut);
			}
		}finally{
			IOUtil.close(writerOut);
		}
	}
	
	/**
	 * 根据字符串模板生成模板实例
	 * @param context 参数域
	 * @param templateStr 字符串模板
	 * @param writerOut 输出流
	 */
	public static void generateTemplateStrInstance(VelocityContext context,String templateStr, Writer writerOut){
		try{
			if(EmptyUtils.isNotEmptys(context, templateStr, writerOut)){
				Velocity.evaluate(context, writerOut, "", templateStr);
			}
		}finally{
			IOUtil.close(writerOut);
		}
	}
	
	/**
	 * 根据字符串模板生成模板实例
	 * @param context 参数域
	 * @param templateStr 字符串模板
	 * @return
	 */
	public static String generateTemplateStrInstanceToString(VelocityContext context,String templateStr){
		StringWriter stringWriter = new StringWriter();
		generateTemplateStrInstance(context, templateStr, stringWriter);
		return stringWriter.toString();
	}
	
	
	/**
	 * 根据字符串模板生成input输入流
	 * @param context 参数域
	 * @param templateStr 字符串模板
	 * @return
	 */
	public static InputStream generateTemplateStrInstanceToInput(VelocityContext context,String templateStr){
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		generateTemplateStrInstance(context, templateStr, new OutputStreamWriter(out));
		return new ByteArrayInputStream(out.toByteArray());
	}
	
	/**
	 * 根据字符串模板生成Reader输入流
	 * @param context 参数域
	 * @param templateStr 字符串模板
	 * @return
	 */
	public static Reader generateTemplateStrInstanceToReader(VelocityContext context,String templateStr){
		String str = generateTemplateStrInstanceToString(context, templateStr);
		return new StringReader(str);
	}
	
	/**
	 * 根据模板路径和参数生成模板实例
	 * @param context 参数域
	 * @param templatePath 模板路径,相对于classpath的绝对路径(前面要加/)
	 * @param out 输出流
	 */
	public static void generateTemplateInstance(VelocityContext context,String templatePath,OutputStream out){
		Template template  = generateTemplate(templatePath);
		generateTemplateInstance(context, template, new OutputStreamWriter(out));
	}
	
	/**
	 * 根据模板路径和参数生成模板实例 并将模板实例转换为字符串返回
	 * @param context 参数域
	 * @param templatePath 模板路径,相对于classpath的绝对路径(前面要加/)
	 * @return
	 */
	public static String generateTemplateInstanceToString(VelocityContext context,String templatePath){
		Template template  = generateTemplate(templatePath);
		StringWriter stringWriter = new StringWriter();
		generateTemplateInstance(context, template, stringWriter);
		return stringWriter.toString();
	}
	
	/**
	 * 根据模板路径和参数生成模板实例 并将模板实例转换为Input输入流
	 * @param context 参数域
	 * @param templatePath 模板路径,相对于classpath的绝对路径(前面要加/)
	 * @return
	 */
	public static InputStream generateTemplateInstanceToInput(VelocityContext context,String templatePath){
		Template template  = generateTemplate(templatePath);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		generateTemplateInstance(context, template, new OutputStreamWriter(out));
		return new ByteArrayInputStream(out.toByteArray());
	}
	
	/**
	 * 根据模板路径和参数生成模板实例 并将模板实例转换为Input输入流
	 * @param context 参数域
	 * @param template 模板对象
	 * @return
	 */
	public static InputStream generateTemplateInstanceToInput(VelocityContext context,Template template){
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		generateTemplateInstance(context, template, new OutputStreamWriter(out));
		return new ByteArrayInputStream(out.toByteArray());
	}
	
	/**
	 * 根据模板路径和参数生成模板实例 并将模板实例转换为Reader输入流
	 * @param context 参数域
	 * @param templatePath 模板路径,相对于classpath的绝对路径(前面要加/)
	 * @return
	 */
	public static Reader generateTemplateInstanceToReader(VelocityContext context,String templatePath){
		String str = generateTemplateInstanceToString(context, templatePath);
		return new StringReader(str);
	}
	
	
	
}
